package com.xnx3.j2ee.system.responseBody;

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xnx3.j2ee.util.ConsoleUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * 针对json接口的 ResponseBody 的json返回值拦截处理
 * @author: 管雷鸣
 */
@ControllerAdvice
public class WMResponseBody implements ResponseBodyAdvice {
	@Override
	public Object beforeBodyWrite(Object body, MethodParameter arg1,
									MediaType arg2, Class arg3, ServerHttpRequest request,
									ServerHttpResponse arg5) {
		ResponseBodyManage manage = (ResponseBodyManage) body.getClass().getAnnotation(ResponseBodyManage.class);
		if(manage == null) {
			//没有这个注解标注，那么不过滤什么字段，原样返回
			return body;
		}
		
		//如果没有要忽略的字段，也不需要给null重新赋值，那么将之原样返回
		if((manage.ignoreField() == null || manage.ignoreField().length < 1) && manage.nullSetDefaultValue() == false) {
			return body;
		}
		
		/***** nullSetDefaultValue 起作用 ******/
		String bodyStr;
		if(manage.nullSetDefaultValue()) {
			bodyStr = com.alibaba.fastjson.JSONObject.toJSONString(body,
					SerializerFeature.WriteMapNullValue,
					SerializerFeature.WriteNullListAsEmpty , // List字段如果为null,输出为[],而非null
					SerializerFeature.WriteNullStringAsEmpty, //字符类型字段如果为null,输出为”“,而非null
					SerializerFeature.WriteNullNumberAsZero, //数值字段如果为null,输出为0,而非null
					SerializerFeature.WriteNullBooleanAsFalse ,//Boolean字段如果为null,输出为false,而非null
					SerializerFeature.SkipTransientField , //类中的Get方法对应的Field是transient，序列化时将会被忽略。默认为true
					SerializerFeature.DisableCircularReferenceDetect, //消除对同一对象循环引用的问题，默认为false
					SerializerFeature.WriteEnumUsingName
					);
			bodyStr = bodyStr.replaceAll("\":null", "\":{}");	//将所有空直接转化为 {} 空对象
		}else {
			bodyStr = com.alibaba.fastjson.JSONObject.toJSONString(body, SerializerFeature.WriteMapNullValue);
		}
		
		/***** ignoreField 起作用 ******/
		if((manage.ignoreField() != null && manage.ignoreField().length > 0)) {
			try {
				JSONObject json = net.sf.json.JSONObject.fromObject(bodyStr);
				String[] ignore = manage.ignoreField();
//				System.out.println(JSONArray.fromObject(ignore));
				jsonDispose(json, ignore);
				bodyStr = json.toString();
			} catch (Exception e) {
				ConsoleUtil.error(bodyStr);
				e.printStackTrace();
				return bodyStr;
			}
		}
		
		com.alibaba.fastjson.JSONObject returnJson = (com.alibaba.fastjson.JSONObject) com.alibaba.fastjson.JSONObject.parseObject(bodyStr);
		return returnJson;
	}

	@Override
	public boolean supports(MethodParameter arg0, Class arg1) {
		return true;
	}
	
	public static void jsonDispose(Object obj, String[] ignoreFields) {
		if(obj == null) {
			return;
		}
		if(obj instanceof JSONObject) {
			//如果是json对象，那么继续向下遍历
			JSONObject json = (JSONObject)obj;
			
			JSONArray namesArray = json.names();
			
			for(int i=0; i<namesArray.size(); i++) {
				String key = namesArray.getString(i);
				Object subObj = json.get(key);
				if(isJsonObject(subObj)) {
					//是json，继续向下遍历
					jsonDispose(subObj, ignoreFields);
				}else {
					//不是json了，那么判断key是否在忽略的字段里面
					if(isIgnoreField(key, ignoreFields)) {
						//要删除
//						System.out.println("delete  --- "+key);
						json.remove(key);
					}
				}
			}
		}else if(obj instanceof JSONArray) {
			//如果是json数组，那么继续往下遍历
			JSONArray jsonArray = (JSONArray)obj;
			for (int i = 0; i < jsonArray.size(); i++) {
				Object subObj = jsonArray.get(i);
				if(isJsonObject(subObj)) {
					//是json，继续向下遍历
					jsonDispose(subObj, ignoreFields);
				}else {
					//不是json了，那么忽略之
					
				}
			}
		}
		
	}
	
	/**
	 * 判断当前key是否在忽略字段之内
	 * @param key json返回值中key值
	 * @param ignoreFields 忽略的字段，数组形式，每个忽略字段都是数组中的一个
	 * @return 如果key是在忽略字段之内，那返回true，如果不是忽略字段，返回false
	 */
	public static boolean isIgnoreField(String key, String[] ignoreFields) {
		for (int i = 0; i < ignoreFields.length; i++) {
			if(ignoreFields[i].equalsIgnoreCase(key)) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 判断某个对象是否是json对象或者json数组
	 * @param obj 对象
	 * @return 是，则返回true，不是json对象或数组，返回false
	 */
	public static boolean isJsonObject(Object obj) {
		if(obj == null) {
			return false;
		}
		if(obj instanceof JSONObject || obj instanceof JSONArray) {
			//json对象或数组
			return true;
		}else {
			return false;
		}
	}
	
	public static boolean isDelete(Object obj) {
		if(obj instanceof JSONObject || obj instanceof JSONArray) {
			//json对象或数组
			return false;
		}else{
			//正常数据，判断是否是删除的字段
			return false;
		}
	}
	
	public static void main(String[] args) {
		String bodyStr = "{\"info\":\"admin/index/index.do\",\"result\":1,\"token\":\"ccbecc74-912c-4786-9c25-9f415fc225f3\",\"user\":{\"authority\":\"9\",\"currency\":0,\"email\":\"\",\"freezemoney\":0,\"head\":\"default.png\",\"id\":1,\"isfreeze\":0,\"lastip\":\"192.168.31.95\",\"lasttime\":1676965707,\"money\":0,\"nickname\":\"总管理\",\"password\":\"94940b4491a87f15333ed68cc0cdf833\",\"phone\":\"17000000002\",\"referrerid\":0,\"regip\":\"127.0.0.1\",\"regtime\":1512818402,\"salt\":\"9738\",\"sex\":\"\",\"sign\":\"\",\"username\":\"admin\",\"version\":1}}";
		System.out.println(bodyStr);
		
		String ignoreField = "password,salt,version,currency,nickname,authority,money,head,isfreeze,sex,sign,freezemoney,referrerid";
		
		net.sf.json.JSONObject json = net.sf.json.JSONObject.fromObject(bodyStr);
		jsonDispose(json, ignoreField.split(","));
		System.out.println(json);
	}
}
